package net.sansi.v3correctserver.entity.photorec;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import net.sansi.v3correctserver.entity.IntPoint;
import net.sansi.v3correctserver.entity.color.PhotoColor;
import net.sansi.v3correctserver.util.CorrectUtil;
import net.sansi.v3correctserver.util.RGBUtil;

import java.util.HashSet;
import java.util.Set;

/**
 * Created by Fang
 * create time : 2024/11/6
 * IDE : IntelliJ IDEA
 * <p>
 * 灯点节点
 */

@Slf4j
public class LedNode {

    // 在矩阵中的位置
    @Getter
    @Setter
    private IntPoint matrixPos;
    // LED 灯点的邻居
    public LedNode[] neighbors = new LedNode[4];

    // 灯点围栏，用于计算灯点的范围
    // [ 上，右，下，左 ]
    public int[] ledFence = new int[]{Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE};

    // 亮度围栏
    public int[] brightFence;

    /**
     * 获取灯点的中心
     *
     * @return 中心
     */
    public IntPoint getPhotoPos() {
        return new IntPoint((ledFence[1] + ledFence[3]) >> 1, (ledFence[0] + ledFence[2]) >> 1);
    }

    /**
     * 获取灯点围栏面积
     *
     * @return 面积
     */
    public int getLedFenceArea() {
        return (ledFence[2] - ledFence[0] + 1) * (ledFence[1] - ledFence[3] + 1);
    }

    /**
     * 获取亮度围栏面积
     *
     * @return 面积
     */
    public int getBrightFenceArea() {
        return (brightFence[2] - brightFence[0] + 1) * (brightFence[1] - brightFence[3] + 1);
    }


    // 该灯点所属像素点位置
    public Set<Long> pixels = new HashSet<>();

    // 轮廓点集合
    public Set<Long> borderPixels = new HashSet<>();

    /**
     * 是否是我的像素点
     *
     * @param px 相片x位置
     * @param py 相片y位置
     * @return 是否是我的像素点
     */
    public boolean isMyPixel(int px, int py) {
        return pixels.contains(CorrectUtil.xy2Long(px, py));
    }

    /**
     * 获取灯点面积
     *
     * @return 面积
     */
    public int getArea() {
        return pixels.size();
    }


    /**
     * 添加该灯点所属像素点位置
     *
     * @param px       相片 x 位置
     * @param py       相片 y 位置
     * @param isBorder 是否为轮廓点
     */
    public void addPixel(int px, int py, boolean isBorder) {
        long p = CorrectUtil.xy2Long(px, py);
        pixels.add(p);
        if (isBorder) borderPixels.add(p);
        ledFence[0] = Math.min(py, ledFence[0]);
        ledFence[1] = Math.max(px, ledFence[1]);
        ledFence[2] = Math.max(py, ledFence[2]);
        ledFence[3] = Math.min(px, ledFence[3]);
    }


    // LED 灯点的RGB累加值
    @Getter
    public PhotoColor ledColor = new PhotoColor();

    @Getter
    public double brightness = 0;
    @Getter
    private double rgbBright = 0;
    @Getter
    private double hslBright = 0;
    @Getter
    private double hsvBright = 0;
    @Getter
    private double xyzBright = 0;

    /**
     * 添加亮度
     *
     * @param color 颜色
     */
    public void addBright(PhotoColor color) {
        addLedColor(color);
        //addRGBBright(color);
        //addHSLBright(color);
        //addHSVBright(color);
        //addXYZBright(color);
    }

    /**
     * 添加灯点颜色
     *
     * @param color 颜色
     */
    private void addLedColor(PhotoColor color) {
        ledColor.add(color);
    }

    /**
     * 添加 RGB 亮度
     *
     * @param color 颜色
     */
    private void addRGBBright(PhotoColor color) {
        rgbBright += color.getBrightness();
    }

    /**
     * 添加 HSL 亮度
     *
     * @param color 颜色
     */
    private void addHSLBright(PhotoColor color) {
        double max = Math.max(color.getR(), Math.max(color.getG(), color.getB()));
        double min = Math.min(color.getR(), Math.min(color.getG(), color.getB()));
        hslBright += (max + min) / 2;
    }

    /**
     * 添加 HSV 亮度
     *
     * @param color 颜色
     */
    private void addHSVBright(PhotoColor color) {
        double max = Math.max(color.getR(), Math.max(color.getG(), color.getB()));
        hsvBright += max;
    }

    /**
     * 添加 XYZ 亮度
     *
     * @param color 颜色
     */
    private void addXYZBright(PhotoColor color) {
        double[] xyz = RGBUtil.rgbToXyz(color.getR(), color.getG(), color.getB());
        xyzBright += xyz[1];
    }

    public double getBrightness(int colorIdx) {
        return ledColor.getBrightness(colorIdx);
    }

}
